﻿#region 
/*---------------------------------------------------------------- 
* 项目名称 ：Mrc.Data.Filter 
* 项目描述 ： 
* 类 名 称 ：PermissionFilter 
* 类 描 述 ： 
* 所在的域 ：DESKTOP-HKKGEJ7
* 命名空间 ：Mrc.Data.Filter
* 机器名称 ：DESKTOP-HKKGEJ7 
* CLR 版本 ：4.0.30319.42000 
* 作 者 ：mrc 
* 创建时间 ：2019/2/15 21:15:52 
* 更新时间 ：2019/2/15 21:15:52 
* 版 本 号 ：v1.0.0.0 
******************************************************************* 
* Copyright @ mrc 2019. All rights reserved. *******************************************************************
 //----------------------------------------------------------------*/
#endregion


using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Collections.Generic;
using System;
using Mrc.Entity;
using DotNetEx;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Mrc.Application
{
    //https://www.cnblogs.com/freeliver54/p/6247810.html
    public class PermissionFilter : IAuthorizationFilter
    {
        public virtual void OnAuthorization(AuthorizationFilterContext filterContext)
        {
            var httpContext = filterContext.HttpContext;
            if (filterContext.Result != null)
                return;
            if (this.SkipAuthorize(filterContext.ActionDescriptor))
            {
                return;
            }
            List<string> permissionCodes = filterContext.ActionDescriptor.FilterDescriptors.Where(a => a.Filter is PermissionAttribute).Select(a => a.Filter as PermissionAttribute).Select(a => a.Code).ToList();
            if (permissionCodes.Count == 0)
            {
                return;
            }
            string msg = null;
            int responseStatusCode = httpContext.Response.StatusCode;
            //说明处于登录状态，则开始验证当前登录用户是否拥有访问权限
            if (this.HasExecutePermission(filterContext, permissionCodes))
            {
                return;
            }
            else
            {
                msg = "抱歉，您无当前操作权限";
                responseStatusCode = 403;
            }
            HttpRequest httpRequest = httpContext.Request;
            if(httpRequest.IsAjaxRequest())
            {
                AjaxResult result = AjaxResult.CreateResult(ResultStatus.Unauthorized, msg);
                string json = JsonHelper.Serialize(result);
                ContentResult contentResult = new ContentResult() { Content = json };
                contentResult.StatusCode = 200;
                filterContext.Result = contentResult;
                return;
            }
            else
            {
                string url = httpContext.Content("/home/PageNoAuth");
                url = string.Concat(url, "?returnUrl=", httpRequest.Path);
                RedirectResult redirectResult = new RedirectResult(url);
                filterContext.Result = redirectResult;
                return;
            }
        }
        protected virtual bool SkipAuthorize(ActionDescriptor actionDescriptor)
        {
            bool skipAuthorize = actionDescriptor.FilterDescriptors.Where(a => a.Filter is SkipPermissionAttribute).Any();
            if (skipAuthorize)
            {
                return true;
            }
            return false;
        }
        protected virtual bool HasExecutePermission(AuthorizationFilterContext filterContext, List<string> permissionCodes)
        {
            return true;
        }
    }

    public class WebPermissionFilter : PermissionFilter
    {
        public WebPermissionFilter()
        {

        }
        protected override bool HasExecutePermission(AuthorizationFilterContext filterContext, List<string> permissionCodes)
        {
            return PermissionAuthHelper.HasPermission(filterContext.HttpContext, permissionCodes);
        }
    }


    /// <summary>
    /// 验证是否包含权限
    /// </summary>
    public static class PermissionAuthHelper
    {
        public const string PermissionPrefixKey = "P_Check:";
        public static bool HasPermission(HttpContext httpContext, List<string> permissionCodes)
        {
            AdminSession session = httpContext.Items["user"] as AdminSession;
            if (session == null) return false;
            if (session.AccountName == "admin") return true;
            List<string> usePermits = null;
            usePermits = httpContext.Items["User_Permits"] as List<string>;
            foreach (string permit in permissionCodes)
            {
                if (!usePermits.Any(a => a == permit))
                    return false;
            }
            return true;
        }
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class PermissionAttribute : Attribute, IFilterMetadata
    {
        public PermissionAttribute()
        {
        }
        public PermissionAttribute(string code)
        {
            this.Code = code;
        }
        public string Code { get; set; }
    }
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class SkipPermissionAttribute : Attribute, IFilterMetadata
    {
    }
}
